<?php

/* memcache host */
define("__MEMHOST", "172.25.249.1");
/* memcache port */
define("__MEMPORT", "11211");

/* This interface should be implemented by any class that wishes to act as a
 * cache provider.
 */
interface Cache
{
  /* Cache a variable in the data store */
  public function item_set( $key, $var, $ttl = 0);

  /* Fetch a stored variable from the cache */
  public function item_get($key);

  /* Removes a stored variable from the cache */
  public function item_delete($key);

  /* Clears the cache */
  public function clear();

  /* Stores a file in the cache */
  public function file_add($filename);
}

/* The RemoteCache class extends the Memcache class to provide a Level-2 cache
 * that we can use. It has to be noted that this cache is not guaranteed to be
 * on the local machine, so there is a TCP socket involved that created
 * overhead.
 */
class RemoteCache implements Cache
{
  static private $m_objMem = NULL;

  public function __construct($settings)
  {
    $this->settings=$settings;
  	$this->connect();
  }

	private function connect()
	{
		if (self::$m_objMem == NULL)
		{
			$memcache = new Memcache();
			$this->servers	= (array) $this->settings->memcached->servers;
			$servers	= $this->servers['server'];
			if (count($servers) > 0) {
				foreach($servers as $s)	{
					# Connect server, to add it to memcache pool
					$rs = $memcache->addServer((string)$s->ip, (string)$s->port);
					if ($rs === true) {
						$nrConnected++;
					}
				}
			} else {
				return false;
			}

			if ($nrConnected == 0) {
				return false;
			} else {
				self::$m_objMem = $memcache;
				return $memcache;
			}
			return true;
		}
	}

  public function item_set($key, $var, $ttl = 0)
  {
  	self::$m_objMem->delete($key);
	//echo "setting var: <hr/>".print_r($var,1)."<hr /> met key $key";
    return self::$m_objMem->add($key, $var, false, $ttl);
  }

  public function item_get($key)
  {
    return self::$m_objMem->get($key);
  }

  public function item_delete($key)
  {
    return self::$m_objMem->delete($key);
  }

  public function clear()
  {
    return self::$m_objMem->flush();
  }

  public function file_add($filename)
  {
    if (file_exists($filename))
    {
      return $this->item_add($filename, file_get_contents($filename), 0);
    }
    return false;
  }
}


class LocalCache implements Cache
{
	public function __construct()
	{}

	/* Cache a variable in the data store */
	public function item_set($key, $var, $ttl = 0)
	{
		return apc_store($key, $var, $ttl);
	}

	/* Removes a stored variable from the cache */
	public function item_delete($key)
	{
		return apc_delete($key);
	}

	/* Fetch a stored variable from the cache */
	public function item_get($key)
	{
		return apc_fetch($key);
	}

	/* Clears the cache */
	public function clear()
	{
		return apc_cache_clear();
	}

	/* Stores a file in the cache */
	public function file_add($filename)
	{
		return apc_compile_file($filename);
	}
}

/* The L12Cache is a combination between APC and memcache. It wil first try to get the data from the Level-1 cache.
   if this is not available, it will try to fetch it from Level-2 Memcache, if found it will write the APC L1 cache.
   If none is found it will return false
*/

class L12Cache implements Cache
{
	static private $m_objMem = NULL;


	public function __construct($settings)
	{
		$this->settings=$settings;
	}

	private function connect()
	{
		if (self::$m_objMem == NULL)
		{
			$memcache = new Memcache();
			$this->servers	= (array) $this->settings->memcached->servers;
			$servers	= $this->servers['server'];
			if (count($servers) > 0) {
				foreach($servers as $s)	{
					# Connect server, to add it to memcache pool
					$rs = $memcache->addServer((string)$s->ip, (string)$s->port);
					if ($rs === true) {
						$nrConnected++;
					}
				}
			} else {
				return false;
			}

			if ($nrConnected == 0) {
				return false;
			} else {
				self::$m_objMem = $memcache;
				return $memcache;
			}
		return true;
		}
	}

	/* Cache a variable in the data store */
	public function item_set($key, $var, $ttl = 0)
	{
		apc_store($key, $var, $ttl);
		$settings = simplexml_load_file(Cabbie::$approot."/config/config.xml");
		$R = new RemoteCache($settings);
		return $R->item_set($key, $var, $ttl);
	}

	/* Removes a stored variable from the cache */
	public function item_delete($key)
	{
		if (self::$m_objMem == NULL)
		{
			$this->connect();
			$rs=apc_delete($key);
			return self::$m_objMem->delete($key);
		}
	}

	/* Fetch a stored variable from the cache */
	public function item_get($key)
	{
		$rs=apc_fetch($key);
		if($rs === false) {
			if (self::$m_objMem == NULL)
			{
				$this->connect();
				$rs=self::$m_objMem->get($key);
				if($rs !== false)
				{
					apc_store($key, $rs, $ttl);
				}
			}
		}
		return $rs;
	}

	/* Clears the cache */
	public function clear()
	{
		$this->connect();
		$rs= self::$mem_objMem->flush();
		return apc_cache_clear();
	}

	/* Stores a file in the cache */
	public function file_add($filename)
	{
		if (file_exists($filename))
		{
			$this->connect();
			$this->item_add($filename, file_get_contents($filename), 0);
			return apc_compile_file($filename);
		}
		return false;
	}
}
?>